package cpu

// PCRIndex PCR寄存器索引类型
type PCRIndex struct {
	Index    int
	BitCount int
}

// PCR索引
var (
	CSR_FFLAGS = PCRIndex{Index: 0x001, BitCount: 64}
	CSR_FRM    = PCRIndex{Index: 0x002, BitCount: 64}
	CSR_FCSR   = PCRIndex{Index: 0x003, BitCount: 64}

	CSR_SUP0      = PCRIndex{Index: 0x500, BitCount: 64}
	CSR_SUP1      = PCRIndex{Index: 0x501, BitCount: 64}
	CSR_EPC       = PCRIndex{Index: 0x502, BitCount: 64}
	CSR_BADVADDR  = PCRIndex{Index: 0x503, BitCount: 64}
	CSR_PTBR      = PCRIndex{Index: 0x504, BitCount: 64}
	CSR_ASID      = PCRIndex{Index: 0x505, BitCount: 64}
	CSR_COUNT     = PCRIndex{Index: 0x506, BitCount: 32}
	CSR_COMPARE   = PCRIndex{Index: 0x507, BitCount: 32}
	CSR_EVEC      = PCRIndex{Index: 0x508, BitCount: 64}
	CSR_CAUSE     = PCRIndex{Index: 0x509, BitCount: 64}
	CSR_STATUS    = PCRIndex{Index: 0x50A, BitCount: 32}
	CSR_HARTID    = PCRIndex{Index: 0x50B, BitCount: 64}
	CSR_IMPL      = PCRIndex{Index: 0x50C, BitCount: 64}
	CSR_FATC      = PCRIndex{Index: 0x50D, BitCount: 64}
	CSR_SEND_IPI  = PCRIndex{Index: 0x50E, BitCount: 64}
	CSR_CLEAR_IPI = PCRIndex{Index: 0x50F, BitCount: 64}

	CSR_STATS    = PCRIndex{Index: 0x51C, BitCount: 64}
	CSR_RESET    = PCRIndex{Index: 0x51D, BitCount: 64}
	CSR_TOHOST   = PCRIndex{Index: 0x51E, BitCount: 64}
	CSR_FROMHOST = PCRIndex{Index: 0x51F, BitCount: 64}

	CSR_CYCLE   = PCRIndex{Index: 0xC00, BitCount: 32}
	CSR_TIME    = PCRIndex{Index: 0xC01, BitCount: 64}
	CSR_INSTRET = PCRIndex{Index: 0xC02, BitCount: 64}
)

// status register bit mappings
type SR_TYPE = uint64

const (
	SR_S   SR_TYPE = 0x00000001
	SR_PS  SR_TYPE = 0x00000002
	SR_EI  SR_TYPE = 0x00000004
	SR_PEI SR_TYPE = 0x00000008
	SR_EF  SR_TYPE = 0x00000010
	SR_U64 SR_TYPE = 0x00000020
	SR_S64 SR_TYPE = 0x00000040
	SR_VM  SR_TYPE = 0x00000080
	SR_EA  SR_TYPE = 0x00000100
	SR_IM  SR_TYPE = 0x00FF0000
	SR_IP  SR_TYPE = 0xFF000000
)

func statusRegInit() uint64 {
	var srinit uint64 = 0x0
	srinit = srinit & (^SR_EI)
	srinit = srinit | SR_S
	srinit = srinit & (^SR_PS)
	srinit = srinit & (^SR_VM)
	srinit = statusRegForce(srinit)
	return srinit
}

// "hardwired" values that need to be forced every time status reg is modified
func statusRegForce(input uint64) uint64 {
	// force EF to zero here (no FP insts)
	// force U64 to 1 here
	// force S64 to 1 here
	input = input & (^SR_EF)
	input = input | SR_U64 | SR_S64
	return input
}
